package com.cxh.rmsq.net.self

import android.content.Context
import android.content.Intent
import android.os.Handler
import android.os.Looper
import android.text.TextUtils
import android.widget.Toast
import com.aleyn.mvvm.utils.ActivityCollector
import com.cxh.rmsq.common.NetConstant
import com.cxh.rmsq.net.HttpLogInterceptor
import com.cxh.rmsq.net.SealTalkUrl
import com.cxh.rmsq.ui.activity.LoginActivity
import com.google.gson.Gson
import io.rong.imlib.model.RCIMProxy
import okhttp3.*
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.io.IOException
import java.net.InetSocketAddress
import java.net.Proxy
import java.nio.charset.Charset
import java.security.SecureRandom
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import java.util.concurrent.TimeUnit
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.X509TrustManager


/**
 *   @auther : Aleyn
 *   time   : 2019/09/04
 */
class RetrofitSelfClient {

    companion object {
        fun getInstance() = SingletonHolder.INSTANCE
        private lateinit var retrofit: Retrofit
    }

    private object SingletonHolder {
        val INSTANCE = RetrofitSelfClient()
    }

    init {
        retrofit = Retrofit.Builder()
            .client(getOkHttpClient())
//            .client(getUnsafeOkHttpClient(AppProxyManager.getInstance().getProxy())!!)
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl(SealTalkUrl.DOMAIN)
            .build()
    }

    private fun getOkHttpClient(): OkHttpClient {

        try {
            // Create a trust manager that does not validate certificate chains
            val trustAllCerts = arrayOf<TrustManager>(
                object : X509TrustManager {
                    @Throws(CertificateException::class)
                    override fun checkClientTrusted(
                        chain: Array<X509Certificate>, authType: String
                    ) {
                    }

                    @Throws(CertificateException::class)
                    override fun checkServerTrusted(
                        chain: Array<X509Certificate>, authType: String
                    ) {
                    }

                    override fun getAcceptedIssuers(): Array<X509Certificate> {
                        return arrayOf()
                    }
                }
            )

            // Install the all-trusting trust manager

            // Install the all-trusting trust manager
            val sslContext = SSLContext.getInstance("SSL")
            sslContext.init(null, trustAllCerts, SecureRandom())
            // Create an ssl socket factory with our all-trusting manager
            // Create an ssl socket factory with our all-trusting manager
            val sslSocketFactory = sslContext.socketFactory


            return OkHttpClient.Builder()
                .connectTimeout(20L, TimeUnit.SECONDS)
                .addNetworkInterceptor(HttpLogInterceptor())
                .addInterceptor(AddHeaderInterceptor())
                .addInterceptor(object : Interceptor {
                    override fun intercept(chain: Interceptor.Chain): Response {
                        //从chain对象中可以获取到request和response，想要的数据都可以从这里获取
                        var request = chain.request()
//                        request = addHeaders(request)
                        //获取response对象
                        val response = chain.proceed(request)
                        val build = response.newBuilder().build()

                        val responseBody = response.body
                        val source = responseBody!!.source()
                        source.request(java.lang.Long.MAX_VALUE) // Buffer the entire body.
                        val buffer = source.buffer()
                        var charset = Charset.forName("UTF-8")
                        val contentType = responseBody.contentType()
                        if (contentType != null) {
                            charset = contentType.charset(Charset.forName("UTF-8"))
                        }
                        val entity = Gson().fromJson<BaseResult<Any>>(
                            buffer.clone().readString(charset),
                            BaseResult::class.java
                        )
                        if (entity.code == 401) {

                            var accessToken = com.blankj.utilcode.util.SPUtils.getInstance().getString("accessToken", "")
                            if (!TextUtils.isEmpty(accessToken)) {
                                Handler(Looper.getMainLooper()).post {
                                    ActivityCollector.finishAll()
                                    Toast.makeText(ActivityCollector.getCurrentActivity(),"会话失效，请重新登录！",Toast.LENGTH_SHORT).show()
                                    ActivityCollector.getCurrentActivity().startActivity(Intent(ActivityCollector.getCurrentActivity(),LoginActivity::class.java))
//                        ActivityCollector.getCurrentActivity().finish()
                                }
                            }}
                        return build
                    }
                })
                .writeTimeout(20L, TimeUnit.SECONDS)
                .connectionPool(ConnectionPool(8, 15, TimeUnit.SECONDS))
                .sslSocketFactory(sslSocketFactory,trustAllCerts[0] as X509TrustManager)
                .hostnameVerifier(HostnameVerifier { hostname, session -> true })
                .build()

        }catch ( e:Exception) {
            throw RuntimeException(e);
        }

    }

    fun <T> create(service: Class<T>?): T =
        retrofit.create(service!!) ?: throw RuntimeException("Api service is null!")

//    private fun addHeaders(request: Request): Request {
////        val token: String = UserUtils.getToken()
//        //由上述packageInfo中获取得到
//        val s =
//            "Brand(${Build.BRAND} ${Build.MODEL}) Android(${Build.VERSION.RELEASE}) Sdk(${Build.VERSION.SDK_INT})"
//
//        // 添加用户登录认证
////            String auth = preferences.getString(NetConstant.API_SP_KEY_NET_HEADER_AUTH, null);
//        val accessToken = SPUtils.get(, "accessToken", "").toString()
//        val params: MutableMap<String, String> = HashMap()
//        params["Authorization"] = "Bearer $accessToken"//token device-sign
//        params["tenant-id"] = "1"//token device-sign
////        params["scene"] = "Android"//标识
////        params["User-Agent"] = s//手机信息
////        params["channel"] = BuildConfig.UMENG_CHANNEL//渠道
////        params["signature"] = jpush_registrationid//极光唯一标识
////        params["x-application-version"] = BuildConfig.VERSION_NAME//标识
////        params["Accept-Encoding"] = "identity"
//        params["Content-Type"] = "application/json"
//
//        val headers = params
//        return request.newBuilder().headers(headers).build()
//    }

    /** 添加header包含cookie拦截器 */
    class AddHeaderInterceptor() : Interceptor {
        var mContext: Context? = null

        fun AddHeaderInterceptor(context: Context?) {
            mContext = context
        }

        @Throws(IOException::class)
        override fun intercept(chain: Interceptor.Chain): Response {
            val builder = chain.request().newBuilder()
//            val preferences = mContext!!.getSharedPreferences(
//                NetConstant.API_SP_NAME_NET, Context.MODE_PRIVATE
//            )
//
//            // 添加cookie
//            val cookieSet = preferences.getStringSet(
//                NetConstant.API_SP_KEY_NET_COOKIE_SET,
//                null
//            ) as HashSet<String>?
//            if (cookieSet != null) {
//                for (cookie in cookieSet) {
//                    builder.addHeader("Cookie", cookie)
//                }
//            }

            // 添加用户登录认证
//            String auth = preferences.getString(NetConstant.API_SP_KEY_NET_HEADER_AUTH, null);
//            val auth = SPUtils.get(mContext, "accessToken", "").toString()
            var auth = com.blankj.utilcode.util.SPUtils.getInstance().getString("accessToken", "")

            //            if (auth != null) {
            builder.addHeader("Authorization", "Bearer $auth")
            builder.addHeader("tenant-id", "1")
            builder.addHeader("Content-Type", "application/json")
            //            }
            return chain.proceed(builder.build())
        }
    }

    /** 接受cookie拦截器  */
    class ReceivedCookiesInterceptor(/*private val mContext: Context*/) : Interceptor {
        var mContext: Context? = null

        fun ReceivedCookiesInterceptor(context: Context?) {
            mContext = context
        }
        @Throws(IOException::class)
        override fun intercept(chain: Interceptor.Chain): Response {
            val originalResponse = chain.proceed(chain.request())
            if (!originalResponse.headers("Set-Cookie").isEmpty()) {
                val cookiesSet = java.util.HashSet(originalResponse.headers("Set-Cookie"))
                val config =
                    mContext?.getSharedPreferences(NetConstant.API_SP_NAME_NET, Context.MODE_PRIVATE)
                        ?.edit()
                config?.putStringSet(NetConstant.API_SP_KEY_NET_COOKIE_SET, cookiesSet)
                config?.apply()
            }
            return originalResponse
        }
    }

    private fun getUnsafeOkHttpClient(proxy: RCIMProxy?): OkHttpClient? {
        return try {
            // Create a trust manager that does not validate certificate chains
            val trustAllCerts = arrayOf<TrustManager>(
                object : X509TrustManager {
                    @Throws(CertificateException::class)
                    override fun checkClientTrusted(
                        chain: Array<X509Certificate>, authType: String
                    ) {
                    }

                    @Throws(CertificateException::class)
                    override fun checkServerTrusted(
                        chain: Array<X509Certificate>, authType: String
                    ) {
                    }

                    override fun getAcceptedIssuers(): Array<X509Certificate> {
                        return arrayOf()
                    }
                }
            )

            // Install the all-trusting trust manager
            val sslContext = SSLContext.getInstance("SSL")
            sslContext.init(null, trustAllCerts, SecureRandom())
            // Create an ssl socket factory with our all-trusting manager
            val sslSocketFactory = sslContext.socketFactory
            val okHttpBuilder: OkHttpClient.Builder = OkHttpClient.Builder()
                .addInterceptor(HttpLogInterceptor())
                .addInterceptor(AddHeaderInterceptor())
                .addInterceptor(ReceivedCookiesInterceptor())
                .connectTimeout(NetConstant.API_CONNECT_TIME_OUT.toLong(), TimeUnit.SECONDS)
                .readTimeout(NetConstant.API_READ_TIME_OUT.toLong(), TimeUnit.SECONDS)
                .writeTimeout(NetConstant.API_WRITE_TIME_OUT.toLong(), TimeUnit.SECONDS)
            if (proxy != null && proxy.isValid) {
                okHttpBuilder.proxy(
                    Proxy(
                        Proxy.Type.SOCKS,
                        InetSocketAddress(proxy.host, proxy.port)
                    )
                )
                if (!TextUtils.isEmpty(proxy.userName)
                    && !TextUtils.isEmpty(proxy.password)
                ) {
                    okHttpBuilder.proxyAuthenticator(
                        Authenticator { route, response ->
                            if (response.code == 407) {
                                // 代理鉴权
                                val credential = Credentials.basic(
                                    proxy.userName, proxy.password
                                )
                                return@Authenticator response.request
                                    .newBuilder()
                                    .header("Proxy-Authorization", credential)
                                    .build()
                            }
                            null
                        })
                }
            }
            okHttpBuilder.sslSocketFactory(sslSocketFactory,trustAllCerts[0] as X509TrustManager)
            okHttpBuilder.hostnameVerifier { hostname, session -> true }
            okHttpBuilder.build()
        } catch (e: java.lang.Exception) {
            throw java.lang.RuntimeException(e)
        }
    }

}